home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / DEV / A-B / 007.FracApp.cpt / UFracApp.p < prev    next >
Text File  |  1988-08-01  |  15KB  |  359 lines

  1. {------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    MacApp Color QuickDraw Fractal Sample Application
  6. #
  7. #    FracApp
  8. #
  9. #    UFracApp.p    -    Pascal Source
  10. #
  11. #    Copyright © 1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.0                    8/88
  15. #
  16. #    Components:    MFracApp.p            August 1, 1988
  17. #                UFracApp.p            August 1, 1988
  18. #                UFracApp.inc1.p        August 1, 1988
  19. #                FracApp.r            August 1, 1988
  20. #                FracApp.make        August 1, 1988
  21. #
  22. #    This is a program to calculate the Mandelbrot set, allowing you to zoom in on areas
  23. #    that are selected with the mouse.  There are some special color tricks played
  24. #    in order to make the program more jazzy.  A special color table is used to give
  25. #    smooth transitions from one color to the next.  Color table animation is also
  26. #    supported, for the wowem effect of flowing Mandelbrot images. 
  27. #    The program is written in MacApp 1.1, which explains why it has a real user
  28. #    interface.  Mandelbrot images take about 30 minutes to calculate.  It is
  29. #    Juggler aware so you can put the program in the background where it will
  30. #    continue to calculate, while you do something more important, like look at 
  31. #    the source code.  It also handles multiple documents, and reading/writing of
  32. #    PICT files using the bottlenecks to minimize the memory hit.
  33. #    
  34. #    This program is intended to be a real world example of handling color in a
  35. #    nontrivial fashion.  As such it has some rather special color requirements,
  36. #    and those don’t match the current system architecture very well.  The program
  37. #    is designed to be compatible with the future, it will not break in future
  38. #    systems.  However, it does not use the Palette Manager, which means that
  39. #    there will be situations where the colors will not look right in either FracApp
  40. #    or another program running under MultiFinder.  The approach that FracApp
  41. #    uses is thus not the preferred Apple approach and does NOT have the Apple
  42. #    seal of approval from engineering.  The only way to get the stamp of approval
  43. #    is to use the Palette Manager.  To do a program of this form, you cannot
  44. #    use the Palette Manager without some extra hacks that are compatibility
  45. #    risks in themselves.  So... use at your own risk.  If you are forced to revise your 
  46. #    program because you followed this as an example, you cannot gripe to Apple, since
  47. #    it is not fully approved.  You just have to change your program, which I hope is no
  48. #    big deal.  You can give this code to other people, as long as they recognize
  49. #    that it is not fully approved too. 
  50. #    
  51. #    Unless you have very special color requirements, you should use the Palette 
  52. #    Manager.  It works for most things, and is much easier to use than the
  53. #    approach taken here.  There are a few things it won’t do of course, leading
  54. #    to this code.  If you can do it, use the Palette Manager and save yourself
  55. #    some grief.
  56. #            Written in MacApp Object Pascal code.
  57. #            Compatibility rating = 2.  (nothing will break, but it may not
  58. #                always look correct.)
  59. #
  60. ------------------------------------------------------------------------------}
  61. {Copyright 1988 by Bob.  All rights reserved, since Bob has all rights.
  62.     February 1, 1988. 
  63.     Written by Bo3b Johnson of Developer Technical Support. }
  64.  
  65. UNIT UFracApp;
  66.  
  67. (*
  68.  
  69. This is a not too small application which can calculate a fractal in full color
  70.     on the Mac II, using direct 881 code for speed.  It saves files on disk as PICT.
  71.     For full info, see the implementation file.
  72.  
  73. *)
  74.  
  75. INTERFACE
  76.  
  77. USES
  78.     {$LOAD FracApp881.LOAD}
  79.         MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,
  80.         UObject, UList, UMacApp,
  81.         PaletteMgr, UPrinting;
  82.     {$LOAD}
  83.  
  84. CONST
  85.  
  86.   {Command numbers}
  87.  
  88.     kSignature                = 'Arf ';        {Application signature}
  89.     kFileType                    = 'PICT';    {File-type code used for document files
  90.                                                         created by this application}
  91.     kFracAppWindowID    = 1001;    {This is passed to NewSimpleWindow as the
  92.                                                         resource ID of the the WIND Resource
  93.                                                         which defines the window for this
  94.                                                         application's documents}
  95.     kStaggerAmount        = 30;
  96.     kPICTHeaderSize         = 512;        { 512 bytes off the file are used for our info and print info. }
  97.     kSelPattern                = 128;        { pattern resource Id. }
  98.     kNewFractal             = 1000;    { item Id for New Fractal menu option. }
  99.     kRotateColors             = 1001;    { item Id for Rotate Colors menu option in Fractal menu. }
  100.     kClut                         = 501;        { Res Id for the clut resource that we use for offscreen. }
  101.     kNumColors                = 195;        { number of colors we animate, and use in calculation. }
  102.     kNumPalette            = 14;        { 14 extra colors in system palette at end of colors. }
  103.     kWrongMachine            = 1000;    { error code if we cannot run, from ForceEnvirons. }
  104.     kBadRotate                = $044C0002;    { message code to use STR# 1100, string 2. }
  105.     
  106.     envDontCare             = 0;            { don't care is always 0, for ForceEnvirons. }
  107.  
  108. TYPE
  109.     { The header record for each of the files saved by FracApp.  This header includes the
  110.         pertinent data that allows a fractal to be restarted, as well as displayed
  111.         on the screen.  The print record follows this info in the first 512 bytes of a file,
  112.         but that info is read by the standard DoRead/DoWrite methods.  Some of the fields
  113.         are LongInts to avoid rounding errors during calculations. }
  114.     FracRecord  = RECORD
  115.         fType:        OSType;            { 4  set as 'Arf ' for these documents. }
  116.         hdrId:        Integer;            { 2  as 'FA' FracApp header ID. }
  117.         version:    Integer;              { 2  file version decides type of file. }
  118.         done:        Boolean;            { 2  if the fractal is finished or not. }
  119.         realMin:    Extended;            { 12  minimum value of fractal on real/p axis. }
  120.         realMax:    Extended;            { 12  maximum value of fractal on real/p axis. }
  121.         imagMin:    Extended;            { 12  minimum on imaginary/q axis. }
  122.         imagMax:    Extended;            { 12  maximum on imaginary/q axis. }
  123.         deltaP:        Extended;            { 12  horizontal step size in fractal space. }
  124.         deltaQ:        Extended;            { 12  vertical step size in fractal space. }
  125.         plotWidth: LongInt;            { 4  width of fractal area in pixels. }
  126.         plotHeight: LongInt;            { 4  height of fractal area in pixels. }
  127.         calcRect:    Rect;                { 8  rectangle surrounding the window it was built for. }
  128.         curRow:    LongInt;            { 4  counter for current pixel position to be done.  Vertical. }
  129.         curCol:        LongInt;            { 4  counter for current pixel.  Horizontal. }
  130.         elapsedTime: LongInt;        { 4  amount of time to do this fractal in seconds. }
  131.     END;  { FracRecord. }
  132.  
  133.  
  134.  
  135. {-------------------------------  Application  -------------------------------}
  136.  
  137.     TFracAppApplication = OBJECT(TApplication)
  138.  
  139.         
  140.         PROCEDURE TFracAppApplication.IFracAppApplication (itsMainFileType: OSType);
  141.             {Initializes the application and globals.}
  142.  
  143.         FUNCTION  TFracAppApplication.DoMakeDocument(
  144.                 itsCmdNumber: CmdNumber): TDocument; OVERRIDE;
  145.             {Launches a TFracAppDocument; called when application's icon is
  146.                 opened, and when New or Open is requested by the user.
  147.                 Every application which uses Documents MUST override this
  148.                 method}
  149.                 
  150.         PROCEDURE  TFracAppApplication.DoIdle (Phase: IdlePhase); OVERRIDE;
  151.             { Performs Idle time processing for the application.  This will do the
  152.                 fractal calculation during the idle times.  It will allow each open
  153.                 view a chance to calculate. }
  154.  
  155.         PROCEDURE TFracAppApplication.DoSetupMenus;  OVERRIDE;
  156.             { Set up the menus choice in Fractal Menu to handle Rotate Colors. }
  157.  
  158.         FUNCTION TFracAppApplication.DoMenuCommand(
  159.                                                 aCmdNumber: CmdNumber): TCommand;  OVERRIDE;
  160.             { Handle the menu choice out of the Fractal Menu for Rotate Colors. }
  161.             
  162.         PROCEDURE TFracAppApplication.RegainControl(checkClipboard: BOOLEAN); 
  163.                 OVERRIDE;
  164.             { When we are switched in we need to reset the color table. }
  165.             
  166.         PROCEDURE TFracAppApplication.AboutToLoseControl(convertClipboard: BOOLEAN);
  167.                 OVERRIDE;
  168.             { When we are switched out we need to restore the color table to be polite. }
  169.             
  170.     END;    { TFracAppApplication }
  171.  
  172.  
  173. {-------------------------------  Document  -------------------------------}
  174.  
  175.     TFracAppDocument = OBJECT(TDocument)
  176.  
  177.         { Now the fields that are special to the fractal itself.  These are the
  178.             variables that make up the display state and the definition of the
  179.             fractal itself.  They are associated with the document so they can
  180.             be stored in a file, and read back in.  Essentially a global state for
  181.             each fractal document. }
  182.  
  183.         fFracHeader:                            FracRecord;            { global state on fractal. }
  184.         fStartTime:                            LongInt;                { starting time of calculations. }
  185.         fBigBuff:                                Ptr;                        { pointer to offscreen data }
  186.         fDrawingDevice:                     GDHandle;                { handle to our offscreen gDevice. }
  187.         fDrawingPort:                        CGrafPtr;                { pointer to drawing buffer. }
  188.  
  189.         fFracAppView:                        TFracAppView;
  190.             {Every document object must preserve references to all the views it
  191.                 creates as fields of the document object, since DoMakeWindows
  192.                 will need to know which views to install in the windows it
  193.                 creates}
  194.  
  195.  
  196.         PROCEDURE  TFracAppDocument.BuildOffWorld (sizeOfDoc: Rect);
  197.             { Allocates offscreen gDevice and port for document data. }
  198.             
  199.         PROCEDURE  TFracAppDocument.SetUpConstants;
  200.             { Sets up starting constants for calculation. }
  201.             
  202.         PROCEDURE      TFracAppDocument.IFracAppDocument;
  203.             {Init routine for the document, sets up the object, then the fractal default state. }
  204.  
  205.         PROCEDURE TFracAppDocument.DoInitialState;  OVERRIDE;
  206.             { Does the work for a New operation, where we start with a new fractal
  207.                 that doesn't have any stored data.  This is set up the view with no
  208.                 data and set up the fractal coordinates to the default. }
  209.  
  210.         PROCEDURE TFracAppDocument.DoMakeWindows; OVERRIDE;
  211.             {Launches the window which will represent the document on the
  212.                 screen.  Every document which has any screen display MUST
  213.                 override this method}
  214.  
  215.         PROCEDURE TFracAppDocument.DoMakeViews(forPrinting: BOOLEAN); OVERRIDE;
  216.             {Launches the view which is seen in the document's window.  Every
  217.                 document which has any screen display or which can be printed
  218.                 MUST override this method}
  219.  
  220.         PROCEDURE TFracAppDocument.DoNeedDiskSpace(VAR dataForkBytes, 
  221.                                                 rsrcForkBytes: LONGINT);  OVERRIDE;
  222.             { Finds out the entire size of the object to be saved into the file so that the
  223.                 correct amount of disk space can be used.  }
  224.  
  225.         PROCEDURE TFracAppDocument.DoRead(aRefNum: INTEGER; rsrcExists,
  226.                                                 forPrinting: BOOLEAN);    OVERRIDE;
  227.             { Reads in the data out of the data fork of the file, and stows it into the
  228.                 document’s bitMap.  Also resets the vars in the document object to match
  229.                 the saved values from the header. }
  230.  
  231.         PROCEDURE TFracAppDocument.DoWrite(aRefNum: INTEGER;
  232.                                                 makingCopy: BOOLEAN);    OVERRIDE;
  233.             { Converts the data in the document’s port into a PICT, then writes that block
  234.                 out to the file, making it into a standard PICT file. }
  235.  
  236.         PROCEDURE TFracAppDocument.FreeData; OVERRIDE;
  237.             {}
  238.  
  239.         PROCEDURE TFracAppDocument.Free; OVERRIDE;
  240.             { Free method for our document.  It disposes the data block of the picture
  241.                 data that was read in from the disk, and kills offscreen stuff. }
  242.  
  243.         PROCEDURE  TFracAppDocument.CalcCity;
  244.             { Does the idle time calculations for the document.  This is for the actual
  245.                 fractal calculations.  It is called by the handler for the Application
  246.                 DoIdle.  It is called for all open documents. }
  247.  
  248.     END;    { TFracAppDocument }
  249.  
  250.  
  251.  
  252. {-------------------------------  View  -------------------------------}
  253.  
  254.     TFracAppView = OBJECT(TView)
  255.  
  256.         { These fields are for the use of the view, and help define our specific view, that
  257.             is the offscreen bitMap representation of the fractal. }
  258.         fSelectionRect:                    Rect;        { rectangle that is current selection }
  259.         fFracAppDocument:                TFracAppDocument;    { handy to avoid type coercion. }
  260.         
  261.         PROCEDURE     TFracAppView.IFracAppView (itsDocument: TFracAppDocument;
  262.                 sizeOfView: Rect);
  263.             { Inits the view object itself. }
  264.  
  265.         PROCEDURE TFracAppView.Draw(area: Rect); OVERRIDE;
  266.             {Draws the view seen in the window.  Every nonblank view MUST
  267.                 override this method}
  268.  
  269.         FUNCTION TFracAppView.DoMenuCommand(
  270.                                                 aCmdNumber: CmdNumber): TCommand;  OVERRIDE;
  271.             { Handle the menu choices for New Fractal out of the Fractal Menu. }
  272.  
  273.         PROCEDURE TFracAppView.DoSetupMenus;  OVERRIDE;
  274.             { Set up the New Fractal menus choice in Fractal Menu, based on selection. }
  275.  
  276.         FUNCTION  TFracAppView.DoMouseCommand(VAR downLocalPoint: Point; 
  277.                         VAR info: EventInfo;
  278.                         VAR hysteresis: Point): TCommand;    OVERRIDE;
  279.             { Handle the mouse events in the view.  Needs to do the selection of a new
  280.                 range for the next fractal to be calculated.  }
  281.  
  282.         PROCEDURE TFracAppView.DoHighlightSelection(fromHL, toHL: HLState); OVERRIDE;
  283.             { Highlight the current selection rectangle if there is one.  }
  284.  
  285.     END;    { TFracAppView }
  286.  
  287.  
  288. {-------------------------------  Command  -------------------------------}
  289.  
  290.     TAreaSelector = OBJECT(TCommand)
  291.  
  292.         { These fields are for the command objects that we use.  The first one we need
  293.             for sure is the selection object to handle the mouse selection in the content
  294.             region of the view.  }
  295.         fOwnerView:    TFracAppView;
  296.         
  297.  
  298.         PROCEDURE TAreaSelector.IAreaSelector(ownerView: TFracAppView; startPt: Point);
  299.             { Initialize the selection object itself.  This basically sets up with IObject,
  300.                 then sets the fSelectionRect to be a minimal rectangle. }
  301.                 
  302.         FUNCTION  TAreaSelector.TrackMouse(aTrackPhase: TrackPhase;
  303.                         VAR anchorPoint, previousPoint, nextPoint: Point;
  304.                         mouseDidMove: BOOLEAN): TCommand;  OVERRIDE;
  305.             { Track the mouse while the button is down in the view. }
  306.  
  307.         PROCEDURE TAreaSelector.TrackFeedback(anchorPoint, nextPoint: Point;
  308.                                         turnItOn, mouseDidMove: BOOLEAN);  OVERRIDE;
  309.             { Feedback that matches better, using the selection pattern. }
  310.             
  311.         PROCEDURE TAreaSelector.TrackConstrain(anchorPoint, previousPoint: Point; 
  312.                         VAR nextPoint: Point);  OVERRIDE;
  313.             { Constrain the mouse movement to be a rect which matches the screen. }
  314.             
  315.     END;    { TAreaSelector }
  316.  
  317. {-------------------------------  GarDevice  -------------------------------}
  318.  
  319. { We also need to keep track of what all gDevices in the system are doing.  In order
  320.     to handle this dynamically a TList is a logical choice.  The GarDevice objects will
  321.     keep information about each gDevice in the system for use in color handling.  
  322.     When used, the Each method will be used to affect every gDevice in the system. }
  323.     
  324.     TGarDevice = OBJECT(TObject)
  325.     
  326.             { The fields for each GarDevice object. }
  327.         fColorTable:            CTabHandle;
  328.         fOldSeed:                LongInt;
  329.         fDevice:                GDHandle;
  330.         fDrawSeed:            LongInt;
  331.  
  332.         PROCEDURE TGarDevice.IGarDevice (OwnerGDevice: GDHandle);
  333.             { Initialize the GarDevice object, add it to the TList of GarDevices. }
  334.             
  335.         PROCEDURE TGarDevice.PoundColors;
  336.             { Force the colors on this GarDevice to have the desired color table if possible. }
  337.             
  338.         PROCEDURE TGarDevice.UnPoundColors;
  339.             { Remove our fascist color mapping when we are switched out.  Restore to
  340.                 what the system was using last. }
  341.                 
  342.         PROCEDURE TGarDevice.RotateColors;
  343.             { Rotate the colors on this GarDevice if we can.  Animation of colors. }
  344.             
  345.         PROCEDURE TGarDevice.SetUpColorMap;
  346.             { Save off the ctSeed of the gDevice owned by this GarDevice, or set up the
  347.                 color search proc to do the zebra fractals if not enough colors. }
  348.                 
  349.         PROCEDURE TGarDevice.RemoveColorMap;
  350.             { Restore the ctSeed of the gDevice, or remove the color search proc. }
  351.     
  352.     END;    { TGarDevice }
  353.  
  354. IMPLEMENTATION
  355.  
  356. {$I UFracApp.inc1.p}
  357.  
  358. END.
  359.